package com.moon.service;

import com.moon.service.manager.AsyncManager;
import com.moon.task.DataDealTask;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author thy
 * @description：todo
 * @date 2024/7/19 10:03
 */
@Slf4j
@Service
public class BusinessService {
    /**
     * 模拟部门员工存储数据
     */
    public static Map<String, List<EmployeeSalaryInfo>> employeeMap =
            Collections.synchronizedMap(new HashMap<>());

    static {
        EmployeeSalaryInfo employeeA = new EmployeeSalaryInfo();
        employeeA.setEmployeeNo("100");
        employeeA.setBaseSalaryAmount(10000);
        employeeA.setSubsidyAmount(3000);

        EmployeeSalaryInfo employeeB = new EmployeeSalaryInfo();
        employeeB.setEmployeeNo("101");
        employeeB.setBaseSalaryAmount(30000);
        employeeB.setSubsidyAmount(3000);

        List<EmployeeSalaryInfo> list = new ArrayList<>();
        list.add(employeeA);
        list.add(employeeB);

        employeeMap.put("10", list);
    }

    @Resource
    private OtherBusinessService otherBusinessService;

    public void testAsync() {
//        for (int i = 0; i < 150; i++) {
//            AsyncMethod();
//        }

//        log.info("执行结果:{}",testCallable(12,45));

//        log.info("执行结果:{}", testCountDownLatch());


//        log.info("执行结果:{}", testCyclicBarrier());
//        testCyclicBarrier();


        for (int i = 0; i < 10; i++) {
            int finalI = i;
            AsyncManager.executorService.execute(() ->testSemaphore(finalI +"0"));
        }
//        try {
//            // 等待所有任务完成，最长等待时间设置为1小时
//            if (!AsyncManager.executorService.awaitTermination(30, TimeUnit.SECONDS)) {
//                log.info("未在指定时间内完成所有任务，强制关闭线程池");
//                AsyncManager.executorService.shutdownNow();
//            }
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//            AsyncManager.executorService.shutdownNow();
//        }

    }

    /**
     * 模拟停车场的车位数-2
     */
    private static final Semaphore semaphore = new Semaphore(2);

    private void testSemaphore(String carNo){
        AsyncManager.executorService.execute(()->{
            if (semaphore.availablePermits() == 0){
                log.info(Thread.currentThread().getName() + ",车牌号->" + carNo + ",车位不足请耐心等待");
            }
            try {
                // 具有阻塞特性，会等待
                semaphore.acquire();
                log.info(Thread.currentThread().getName() + ",车牌号->" + carNo + ",成功进入停车场");
                //模拟车辆在停车场停留的时间（30秒）
                Thread.sleep(5000);
                //释放令牌，腾出停车场车位
                semaphore.release();
                log.info(Thread.currentThread().getName() + ",车牌号->" + carNo + ",驶出停车场");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }

    private void testCyclicBarrier(){
        //查询部门下所有员工信息（模拟）
        List<EmployeeSalaryInfo> employeeSalaryInfos = employeeMap.get("10");
        if (employeeSalaryInfos == null) {
            log.info("部门员工信息不存在");
            return;
        }
        // 统计总工资安全变量
        AtomicInteger totalSalary = new AtomicInteger();
        AtomicReference<BigDecimal> totalSalaryBigDecimal = new AtomicReference<>(BigDecimal.ZERO);

        //开启栅栏-各个线程结束后触发逻辑-不会阻塞主线程
        CyclicBarrier cyclicBarrier = new CyclicBarrier(employeeSalaryInfos.size(),
                () -> log.info("汇总已分别计算出的两个员工的工资->" + totalSalaryBigDecimal.get() + ",执行顺序->B")
        );

//        List<Future<Integer>> result = Collections.synchronizedList(new ArrayList<>());
        employeeSalaryInfos.forEach(emp ->{
//            result.add(
            AsyncManager.executorService.submit(() -> {
                int empSalary = emp.getSubsidyAmount() + emp.getBaseSalaryAmount();
//                Thread.sleep(5000);
                log.info("计算出员工{}", emp.getEmployeeNo() + "的工资->" + empSalary + ",执行顺序->A");
                //汇总总工资
                totalSalary.addAndGet(empSalary);

                totalSalaryBigDecimal.accumulateAndGet(BigDecimal.valueOf(empSalary), BigDecimal::add);
                try {
                    //等待其他线程同步
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
                return empSalary;
            });
//        );
        });

//        AtomicReference<Integer> totalMoney = new AtomicReference<>(0);
//        result.forEach(f ->{
//            try {
//                totalMoney.set(totalMoney.get() + f.get());
//            } catch (InterruptedException | ExecutionException e) {
//                e.printStackTrace();
//            }
//        });
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("统计的总工资是{}",  totalSalaryBigDecimal.get());
    }




    private int testCountDownLatch() {
        Integer[] array = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 101, 102};
        List<Integer> list = new ArrayList<>(Arrays.asList(array));

        // 对数据进行分组处理(6条记录为1组)
        Map<String, List<?>> entityMap = groupListByAvg(list, 5);
        // 根据数据分组数量，确定同步计数器的值
        CountDownLatch latch = new CountDownLatch(entityMap.size());
        List<Future<List<Integer>>> futures = Collections.synchronizedList(new ArrayList<>());

        Iterator<Map.Entry<String, List<?>>> it = entityMap.entrySet().iterator();
        int sum = 0;
        try {
            // 将分组数据分批提交给不同线程处理
            while (it.hasNext()) {
                DataDealTask dataDealTask = new DataDealTask((List<Integer>) it.next().getValue(), latch);
                futures.add(AsyncManager.executorService.submit(dataDealTask));
            }

            // 等待分批处理线程处理完成
            latch.await();

            // 统一处理所有任务的结果
            List<Integer> allResults = new ArrayList<>();
            for (Future<List<Integer>> future : futures) {
                try {
                    allResults.addAll(future.get());
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            }

            // 对所有结果进行后续统一运算
            sum = allResults.stream().mapToInt(Integer::intValue).sum();
            log.info("所有任务结果的总和: " + sum);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return sum;
    }

//    public static void main(String[] args) {
//        testCountDownLatch();
//    }

    // 模拟分组处理方法
    private static Map<String, List<?>> groupListByAvg(List<Integer> list, int groupSize) {
        Map<String, List<?>> groupedMap = new LinkedHashMap<>();
        int index = 0;
        for (int i = 0; i < list.size(); i += groupSize) {
            groupedMap.put("Group" + index, list.subList(i, Math.min(i + groupSize, list.size())));
            index++;
        }
        return groupedMap;
    }

    private Integer testCallable(int x, int y) {
        List<Future<Integer>> results = Collections.synchronizedList(new ArrayList<>());

        results.add(AsyncManager.executorService.submit(
                () -> {
                    log.info("Callable接口执行中......");
                    otherBusinessService.mockSavaData();
                    Thread.sleep(5000);
                    return x + y;
                }));


        AtomicReference<Integer> result = new AtomicReference<>();
        results.forEach(f -> {
            try {
                result.set(f.get(10000, TimeUnit.MILLISECONDS));
            } catch (InterruptedException | ExecutionException | TimeoutException e) {
                e.printStackTrace();
            }
        });
        return result.get();
    }


    private void AsyncMethod() {
        AsyncManager.executorService.execute(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("异步线程执行非核心逻辑。。。。。。。");
        });

        log.info("主线程执行核心逻辑。。。。。。。。。。");
    }

    @Data
    public static class EmployeeSalaryInfo {

        /**
         * 员工编号
         */
        private String employeeNo;
        /**
         * 基本工资
         */
        private Integer baseSalaryAmount;
        /**
         * 补助金额
         */
        private Integer subsidyAmount;
    }


}
